package api

import (
	"context"
	"net/http"
	"portal_api/global"
	"portal_api/models/request"
	"portal_api/models/response"
	"strings"

	pb "portal_api/proto"

	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
)

// PostCreatePortalProver 新建 portal prover
func PostCreatePortalProver(c *gin.Context) {

	// 表单验证
	var req request.CreatePortalProverReq
	if err := c.ShouldBindJSON(&req); err != nil {
		HandleValidatorError(c, err)
		return
	}

	// 存储数据到数据库，要有一个verified字段，或者status状态的字段，用来二次验证交易是否成功
	resp, err := global.PortalRpcClient.CreatePortalRecord(context.Background(), &pb.CreatePortalRecordRequest{
		PortalCode:               req.PortalCode,
		SnapTime:                 req.SnapTime,
		LicensePlateNumber:       req.LicensePlateNumber,
		LicensePlateNumber2:      req.LicensePlateNumber2,
		LicensePlateColor:        req.LicensePlateColor,
		LicensePlateColor2:       req.LicensePlateColor2,
		VehicleColor:             req.VehicleColor,
		VehicleModel:             req.VehicleModel,
		LaneNumber:               req.LaneNumber,
		SnapNumber:               req.SnapNumber,
		DangerousChemicalsSymols: req.DangerousChemicalsSymols,
		DangerousChemicalsType:   req.DangerousChemicalsType,
		AxleType:                 req.AxleType,
		AxleNumber:               req.AxleNumber,
		WheelNumber:              req.WheelNumber,
		VehicleSpeed:             req.VehicleSpeed,
		VehicleLength:            req.VehicleLength,
		TrafficVehicleModel:      req.TrafficVehicleModel,
		ImgExist:                 req.ImgExist,
		BeforeCompress:           req.BeforeCompress,
		AfterCompress:            req.AfterCompress,
		VehicleWidth:             req.VehicleWidth,
		VehicleHeight:            req.VehicleHeight,
		ImageType:                req.ImageType,
		ImageUrl:                 req.ImageUrl,
		RecordId:                 req.RecordId,
		ProvinceCode:             req.ProvinceCode,
		BelongVideoUrl:           req.BelongVideoUrl,
		BelongVideoStartTime:     req.BelongVideoStartTime,
		BelongVideoEndTime:       req.BelongVideoEndTime,
	})

	if err != nil {
		zap.L().Error("portal srv 微服务调用失败",
			zap.Error(err),
			zap.String("province_code",
				req.ProvinceCode),
			zap.String("record_id", req.RecordId),
			zap.String("snap_time", req.SnapTime),
		)
		c.JSON(http.StatusOK, response.Response{
			Code:    http.StatusBadRequest,
			Message: "portal srv 微服务调用失败",
		})
		return
	}

	// 将创建成功的tx的哈希发送到对应的mq中，用来检查交易的状态。
	go func() {
		defer func() {
			if err := recover(); err != nil {
				zap.L().Error("运行时错误", zap.Any("err", err))
			}
		}()
		err := global.Producer.Publish(resp.HashText)
		if err != nil {
			// 记录错误日志
			zap.L().Error("发布mq消息失败",
				zap.Error(err),
				zap.String("tx.Hash",
					resp.HashText),
			)
		}
	}()

	c.JSON(http.StatusOK, response.Response{
		Code:    http.StatusOK,
		Message: "success",
		Data: response.CreatePortalProverResponse{
			HashText: resp.HashText,
			TxHash:   resp.TxHash,
		},
	})
}

func GetPortalRecord(c *gin.Context) {
	// 表单验证
	var req request.GetPortalRecordReq
	if err := c.ShouldBindJSON(&req); err != nil {
		HandleValidatorError(c, err)
		return
	}

	// TODO: 根据province code，看从哪个链读取数据
	resp, err := global.PortalRpcClient.GetPortalRecord(context.Background(), &pb.GetPortalRecordRequest{
		RecordId:     req.RecordId,
		ProvinceCode: req.ProvinceCode,
	})
	if err != nil {
		zap.L().Error("portal srv 微服务调用失败",
			zap.Error(err),
			zap.String("province_code",
				req.ProvinceCode),
			zap.String("record_id", req.RecordId),
		)
		c.JSON(http.StatusOK, response.Response{
			// TODO: 数据库存储失败的错误码
			Code:    http.StatusBadRequest,
			Message: "portal srv 微服务调用失败",
		})
		return
	}

	c.JSON(http.StatusOK, response.Response{
		Code:    http.StatusOK,
		Message: "success",
		Data: response.GetPortalRecordResponse{
			PortalCode:               resp.PortalCode,
			SnapTime:                 resp.SnapTime,
			LicensePlateNumber:       resp.LicensePlateNumber,
			LicensePlateNumber2:      resp.LicensePlateNumber2,
			LicensePlateColor:        resp.LicensePlateColor,
			LicensePlateColor2:       resp.LicensePlateColor2,
			VehicleColor:             resp.VehicleColor,
			VehicleModel:             resp.VehicleModel,
			LaneNumber:               resp.LaneNumber,
			SnapNumber:               resp.SnapNumber,
			DangerousChemicalsSymols: resp.DangerousChemicalsSymols,
			DangerousChemicalsType:   resp.DangerousChemicalsType,
			AxleType:                 resp.AxleType,
			AxleNumber:               resp.AxleNumber,
			WheelNumber:              resp.WheelNumber,
			VehicleSpeed:             resp.VehicleSpeed,
			VehicleLength:            resp.VehicleLength,
			TrafficVehicleModel:      resp.TrafficVehicleModel,
			ImgExist:                 resp.ImgExist,
			BeforeCompress:           resp.BeforeCompress,
			AfterCompress:            resp.AfterCompress,
			VehicleWidth:             resp.VehicleWidth,
			VehicleHeight:            resp.VehicleHeight,
			ImageType:                resp.ImageType,
			ImageUrl:                 resp.ImageUrl,
			RecordId:                 resp.RecordId,
			BlockChainHashCode:       resp.BlockChainHashCode,
			RecordHashCode:           resp.RecordHashCode,
			ProvinceCode:             resp.PortalCode,
			BelongVideoUrl:           resp.BelongVideoUrl,
			BelongVideoStartTime:     resp.BelongVideoStartTime,
			BelongVideoEndTime:       resp.BelongVideoEndTime,
			Status:                   resp.Status,
		},
	})

}

func GetPortalRecordByHash(c *gin.Context) {
	// 表单验证
	var req request.GetPortalRecordByHashReq
	if err := c.ShouldBindUri(&req); err != nil {
		HandleValidatorError(c, err)
		return
	}

	params := strings.Split(req.Hash, ":")
	if len(params) != 3 {
		zap.L().Error("哈希参数错误",
			zap.String("portal record hash",
				req.Hash),
		)
		c.JSON(http.StatusOK, response.Response{
			Code:    http.StatusBadRequest,
			Message: "哈希参数错误",
		})
		return
	}
	// ProvinceCode:RecordId:HashText
	provinceCode := params[0]
	recordId := params[1]

	// TODO: 根据province code，看从哪个链读取数据
	resp, err := global.PortalRpcClient.GetPortalRecord(context.Background(), &pb.GetPortalRecordRequest{
		RecordId:     recordId,
		ProvinceCode: provinceCode,
	})
	if err != nil {
		zap.L().Error("portal srv 微服务调用失败",
			zap.Error(err),
			zap.String("province_code",
				provinceCode),
			zap.String("record_id", recordId),
		)
		c.JSON(http.StatusOK, response.Response{
			// TODO: 数据库存储失败的错误码
			Code:    http.StatusBadRequest,
			Message: "portal srv 微服务调用失败",
		})
		return
	}

	c.JSON(http.StatusOK, response.Response{
		Code:    http.StatusOK,
		Message: "success",
		Data: response.GetPortalRecordResponse{
			PortalCode:               resp.PortalCode,
			SnapTime:                 resp.SnapTime,
			LicensePlateNumber:       resp.LicensePlateNumber,
			LicensePlateNumber2:      resp.LicensePlateNumber2,
			LicensePlateColor:        resp.LicensePlateColor,
			LicensePlateColor2:       resp.LicensePlateColor2,
			VehicleColor:             resp.VehicleColor,
			VehicleModel:             resp.VehicleModel,
			LaneNumber:               resp.LaneNumber,
			SnapNumber:               resp.SnapNumber,
			DangerousChemicalsSymols: resp.DangerousChemicalsSymols,
			DangerousChemicalsType:   resp.DangerousChemicalsType,
			AxleType:                 resp.AxleType,
			AxleNumber:               resp.AxleNumber,
			WheelNumber:              resp.WheelNumber,
			VehicleSpeed:             resp.VehicleSpeed,
			VehicleLength:            resp.VehicleLength,
			TrafficVehicleModel:      resp.TrafficVehicleModel,
			ImgExist:                 resp.ImgExist,
			BeforeCompress:           resp.BeforeCompress,
			AfterCompress:            resp.AfterCompress,
			VehicleWidth:             resp.VehicleWidth,
			VehicleHeight:            resp.VehicleHeight,
			ImageType:                resp.ImageType,
			ImageUrl:                 resp.ImageUrl,
			RecordId:                 resp.RecordId,
			BlockChainHashCode:       resp.BlockChainHashCode,
			RecordHashCode:           resp.RecordHashCode,
			ProvinceCode:             resp.PortalCode,
			BelongVideoUrl:           resp.BelongVideoUrl,
			BelongVideoStartTime:     resp.BelongVideoStartTime,
			BelongVideoEndTime:       resp.BelongVideoEndTime,
			Status:                   resp.Status,
		},
	})

}
